import { fabric } from 'fabric';
import { diyCustomControlRender, userCustomControlRender } from './initEvent';
import { Toast } from 'vant';
import store from '../../store';
let handAccountCanvas = null; // 手账画布对象
let ratioNum = 1; // 画布的width,height比列 1.567745
let canvasContentEl = null // 画布容器
let previous = []; // 历史队列
let future = []; // 未来队列

// 测试计算点
let startPoint = null;
let currentPoint = null;
let endPoint = [];

/**
 * 获取画布尺寸
 * @returns Object width height
 */
async function getCurrentCanvasHeight(CW, CH) {
  let size = {
    width: CW,
    height: CH
  }
  while((canvasContentEl.offsetHeight - 10) < CH) {
    CW -= 10;
    CH = CW * ratioNum
    size = {
      width: CW,
      height: CH
    }
  }
  return size
}

/**
 * 初始化画布
 * design_type 画布类型
 */
 async function initCanvas(design_type) {
  // 画布滚动事件重写
  (function(){
    var defaultOnTouchStartHandler = fabric.Canvas.prototype._onTouchStart;
    fabric.util.object.extend(fabric.Canvas.prototype, { 
      _onTouchStart: function(e) { 
        var target = this.findTarget(e);
        // 点击时没有选择中画布的原素
        if (this.allowTouchScrolling && !target && !this.isDrawingMode) {
          handAccountCanvas.discardActiveObject();
          handAccountCanvas.renderAll();
          return;
        }
        defaultOnTouchStartHandler.call(this, e);
      } 
    });
  })();

  canvasContentEl = document.querySelector(`#canvasContentEl`); // 画布容器
  let CW = window.innerWidth - 24; // 画布初始宽度
  let CH = CW * ratioNum;
  const canvasSize = await getCurrentCanvasHeight(CW, CH); // 获取画布尺寸

  // 初始化画布
  handAccountCanvas = new fabric.Canvas('canvas', {
    isDrawingMode: false, // 开启绘画模式
    width: canvasSize.width, // 画布宽度
    height: canvasSize.height, // 画布高度
    backgroundColor: 'transparent', // 画布背景色
    selection: false, // 是否可以选择
    allowTouchScrolling: false, // 指示在使用触摸屏并在画布上拖动时是否可以滚动浏览器
    enableRetinaScaling: true, // 设置为true时，devicePixelRatio缩放画布以在视网膜屏幕上更好地渲染
    controlsAboveOverlay: true, // 超出clipPath后仍然展示控制条
  })

  // 自定义控件呈现
  if (design_type == 1) {
    diyCustomControlRender();
  } else if (design_type == 2) {
    userCustomControlRender();
  }

  // 监听选中事件
  handAccountCanvas.on('selection:created', () => {
    // 当前选中原素的操作
    const currentObject = handAccountCanvas.getActiveObject();
    
    // 删除默认控件
    currentObject['setControlVisible']('ml', false) // 中左
    currentObject['setControlVisible']('mb', false) // 中下
    currentObject['setControlVisible']('mr', false) // 中右
    currentObject['setControlVisible']('mt', false) // 中上
    currentObject['setControlVisible']('tl', false) // 左上角
    currentObject['setControlVisible']('tr', false) // 上右角
    currentObject['setControlVisible']('bl', false) // 左上角

    store.dispatch('design/setCurrentSelectionElement', currentObject);
    // 图片类型
    if (currentObject && currentObject.type === 'image') {
      store.dispatch('design/setCurrentSelectionType', 'sliderOpacity');
    } else if (currentObject && currentObject.type === 'textbox') {
      store.dispatch('design/setCurrentSelectionType', 'text');
    }
  });

  // 监听取消选择事件
  handAccountCanvas.on('selection:cleared', () => {
    store.dispatch('design/setCurrentSelectionElement', '');
    store.dispatch('design/setCurrentSelectionType', '');
  });

  // 监听更新选择事件
  handAccountCanvas.on('selection:updated', () => {
    // 当前选中原素的操作
    const currentObject = handAccountCanvas.getActiveObject();
    store.dispatch('design/setCurrentSelectionElement', currentObject);
    // 图片类型
    if (currentObject && currentObject.type === 'image') {
      store.dispatch('design/setCurrentSelectionType', 'sliderOpacity');
    } else if (currentObject && currentObject.type === 'textbox') {
      store.dispatch('design/setCurrentSelectionType', 'text');
    }
  });

  // 监听路径
  handAccountCanvas.on('before:path:created', function(opt) {
    var path = opt.path;
    var pathInfo = fabric.util.getPathSegmentsInfo(path.path);
    path.segmentsInfo = pathInfo;
  });

  // 清除path
  handAccountCanvas.on('path:created', function(opt) {
    handAccountCanvas.isDrawingMode = false;
    handAccountCanvas.renderAll();
  });

  // 鼠标按下
  handAccountCanvas.on('mouse:down', (options) => {
    startPoint = options.pointer;
    endPoint.push(startPoint);
  });

  // 移动
  handAccountCanvas.on('mouse:move', async (options) => {
    currentPoint = options.pointer;
    let dep = Math.sqrt(Math.pow((startPoint.x - currentPoint.x), 2) + Math.pow((startPoint.y - currentPoint.y), 2));
    dep = parseInt(dep);
    endPoint.push(currentPoint);
    if (dep > 10 && dep < 12) {
      startPoint = currentPoint;
    }
    const currentObject = handAccountCanvas.getActiveObject();
    store.dispatch('design/setCurrentSelectionElement', currentObject);
  });

  // 弹起
  handAccountCanvas.on('mouse:up', (options) => {
    const activeObj = handAccountCanvas.getActiveObject();
    if (activeObj) {
      // 每次 增删改 操作，都会将当前画布序列化，并压入 previous
      const canvasJson = handAccountCanvas.toJSON();
      previous.push(JSON.stringify(canvasJson));
    }
    endPoint.push(options.pointer);
  });

  // 双指手势取消移动
  handAccountCanvas.on("touch:gesture", () => {
    // getActiveObject 返回当前活动对象
    const activeObj = handAccountCanvas.getActiveObject();
    if (activeObj) {
      activeObj.set({
        lockMovementX: true,
        lockMovementY: true,
      });
    }
  });

}

// 计算出两点的距离
// 两点的距离
async function getDistance(p1, p2){
  let dep = Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2));
  return dep;
}

/**
 * 设置背景
 * type color纯色 img图片背景
 * uri 图片链接
 * color 色值编码
 */
function setCanvasBackground({ type, color, uri }) {
  return new Promise((resolve, reject) => {
    if (type === 'color') {
      handAccountCanvas.backgroundColor = color;
      handAccountCanvas.renderAll();
      resolve();
  
      // 每次 增删改 操作，都会将当前画布序列化，并压入 previous
      // const canvasJson = handAccountCanvas.toJSON();
      // previous.push(JSON.stringify(canvasJson));
    } else {
      fabric.Image.fromURL(uri, async (img) => {
  
        // 设置上传背景，并重置画布大小
        ratioNum = img.height / img.width;
        const canvasSize = await getCurrentCanvasHeight(window.innerWidth - 24, img.height); // 获取画布尺寸
        handAccountCanvas.setDimensions({
          width: canvasSize.width,
          height: canvasSize.height
        })
        handAccountCanvas.setBackgroundImage(img, handAccountCanvas.renderAll.bind(handAccountCanvas), {
          scaleX: handAccountCanvas.width / img.width,
          scaleY: handAccountCanvas.height / img.height
        });
        resolve({
          width: canvasSize.width,
          height: canvasSize.height
        });
  
        // 每次 增删改 操作，都会将当前画布序列化，并压入 previous
        // const canvasJson = handAccountCanvas.toJSON();
        // previous.push(JSON.stringify(canvasJson));
      }, { crossOrigin: 'anonymous' });
    }
  })
}

/**
 * 添加图片
 * options: 配置参数等 id之类
 * uri: 图片链接
 */
function addImage({ options = {}, uri }) {
  return new Promise((resolve, reject) => {
    // let url = 'https://res.guxitk.com/2023/08/26/20230826205251-IMG_8537.png';
    new fabric.Image.fromURL(uri, (img) => {
      // img['setControlVisible']('ml', false) // 中左
      // img['setControlVisible']('mb', false) // 中下
      // img['setControlVisible']('mr', false) // 中右
      // img['setControlVisible']('mt', false) // 中上
      // img['setControlVisible']('tl', false) // 左上角
      // img['setControlVisible']('tr', false) // 上右角
      // img['setControlVisible']('bl', false) // 左上角
      img.set(Object.assign(options, {
        selection: false,
        fill: '#fff',
        opacity: 1,
        padding: 0,
        borderScaleFactor: 1.5,
        crossOrigin: 'anonymous',
        isEdit: true,
        isMove: false,
        isMatting: false,
        selectable: true,
      }));
      // 如果图片的宽度大于200，则缩放到100
      if (img.width > 200) {
        img.scaleToWidth(100);
      }
      handAccountCanvas.add(img);
      handAccountCanvas.viewportCenterObject(img); // 垂直水平居中
      handAccountCanvas.setActiveObject(img);

      // 每次 增删改 操作，都会将当前画布序列化，并压入 previous
      const canvasJson = handAccountCanvas.toJSON();
      previous.push(JSON.stringify(canvasJson));

      resolve();
    }, {crossOrigin: 'anonymous'});
  })
}

// 取消选中的原素
function discardActiveObject() {
  return new Promise((resolve, reject) => {
    handAccountCanvas.discardActiveObject();
    handAccountCanvas.renderAll();
    resolve();
  })
}

// 设置选中元素的透明度
function setActiveObjectOpacity(number, type) {
  return new Promise((resolve, reject) => {
    let activeSelection = handAccountCanvas.getActiveObject();
    activeSelection.set('opacity', number / 100);

    // 每次 增删改 操作，都会将当前画布序列化，并压入 previous
    if (type === 'drag-end') {
      const canvasJson = handAccountCanvas.toJSON();
      previous.push(JSON.stringify(canvasJson));
    }

    handAccountCanvas.renderAll();

    resolve();
  })
}

/**
 * 添加文本
 * content 文本信息
 * type text
 * fontSize 字体大小默认16
 */
function addText({ content = '', type = 'text', fontSize = '32' }) {
  return new Promise((resolve, reject) => {
    let text = new fabric.Textbox(content, {
      fill: '#000000',
      fontSize,
      splitByGrapheme: true,
      editable: false,
      padding: 0,
      width: 80,
      textAlign: 'center',
      shadow: null,
      fontWeight: 'normal',
      borderScaleFactor: 1.5,
      lineHeight: 1.0,
      charSpacing: 0,
      isEdit: true,
      isMove: false,
      selectable: true,
      fontFamilySrc: ''
    })
    // text['setControlVisible']('ml', false) // 中左
    // text['setControlVisible']('mb', false) // 中下
    // text['setControlVisible']('mr', false) // 中右
    // text['setControlVisible']('mt', false) // 中上
    // text['setControlVisible']('tl', false) // 左上角
    // text['setControlVisible']('tr', false) // 上右角
    // text['setControlVisible']('bl', false) // 左上角
    // text['setControlVisible']('mtr', false) // 中上旋转
    handAccountCanvas.add(text);
    handAccountCanvas.viewportCenterObject(text); // 垂直水平居中
    handAccountCanvas.setActiveObject(text);
    handAccountCanvas.renderAll();

    // 每次 增删改 操作，都会将当前画布序列化，并压入 previous
    const canvasJson = handAccountCanvas.toJSON();
    previous.push(JSON.stringify(canvasJson));

    resolve();
  })
}

/**
 * 更改文本框信息
 * @param {*} type 类型 text更改文本信息 decreaseFontSize减小字体大小 increaseFontSize增加字体大小 fontFamily设置字体
 * textAlign对齐方式 shadow阴影 fontWeight字体是否加粗 lineHeight行高 charSpacing字距
 * @param {*} content 内容
 * @returns object
 */
function updateTextBox({ type, content, src }) {
  return new Promise((resolve, reject) => {
    let activeSelection = handAccountCanvas.getActiveObject();
    if (type === 'text') {
      activeSelection.set('text', content);
    } else if (type === 'decreaseFontSize' || type === 'increaseFontSize') {
      activeSelection.set('fontSize', content);
    } else if (type === 'fontFamily') {
      activeSelection.set('fontFamily', content);
      activeSelection.set('fontFamilySrc', src);
    } else if (type === 'color') {
      activeSelection.set('fill', content);
      if (activeSelection.shadow) {
        activeSelection.set('shadow', `${activeSelection.fill} 2px 2px 2px`);
      }
    } else if (type === 'textAlign') {
      activeSelection.set('textAlign', content);
    } else if (type === 'shadow') {
      activeSelection.set('shadow', content);
    } else if (type === 'fontWeight') {
      activeSelection.set('fontWeight', content);
    } else if (type === 'lineHeight') {
      activeSelection.set('lineHeight', parseFloat(content).toFixed(1));
    } else if (type === 'charSpacing') {
      activeSelection.set('charSpacing', content);
    }
    handAccountCanvas.renderAll();

    // 每次 增删改 操作，都会将当前画布序列化，并压入 previous
    const canvasJson = handAccountCanvas.toJSON();
    previous.push(JSON.stringify(canvasJson));

    resolve();
  })
}

/**
 * 更新元素属性
 * type 元素类型
 * flag 开关
 */
function updatedItem(type, flag) {
  return new Promise((resolve, reject) => {
    let activeSelection = handAccountCanvas.getActiveObject();
    if (type === 'edit') {
      activeSelection.set('isEdit', flag);
    } else if (type === 'move') {
      activeSelection.set('lockMovementX', flag);
      activeSelection.set('lockMovementY', flag);
      activeSelection.set('isMove', flag);
    } else if (type === 'selectable') {
      activeSelection.set('selectable', flag);

      // 取消选中
      if (!flag) {
        handAccountCanvas.discardActiveObject();
      }
    } else if (type === 'matting') {
      activeSelection.set('isMatting', flag);
    }

    handAccountCanvas.renderAll();
    // 每次 增删改 操作，都会将当前画布序列化，并压入 previous
    const canvasJson = handAccountCanvas.toJSON();
    previous.push(JSON.stringify(canvasJson));

    resolve();
  })
}

/**
 * 下载字体
 * name字体名称
 * url字体链接
 */
function downLoadFont({ name, url }) {
  return new Promise((resolve, reject) => {
    if (store.state.design.fontList[name]) {
      resolve(name);
    } else {
      Toast.loading({
        message: '加载中',
        position: 'center',
        forbidClick: true,
        duration: 0
      });
      let fontFace = new FontFace(name, `url(${url})`);
      fontFace.load().then(loadedFontFace => {
        document.fonts.add(loadedFontFace);
        store.dispatch('design/setFontList', name);
        Toast.clear();
        resolve(loadedFontFace);
      }).catch(() => {
        reject();
      });
    }
  })
}

/**
 * 获取对象
 */
function getObject() {
  return handAccountCanvas;
}

/**
 * 置底
 */
function itemSendToBack() {
  const currentObject = handAccountCanvas.getActiveObject();
  currentObject.sendToBack();
}

/**
 * 下一层
 */
function itemSendBackwards() {
  const currentObject = handAccountCanvas.getActiveObject();
  currentObject.sendBackwards();
}

/**
 * 置顶
 */
function itemBringToFront() {
  const currentObject = handAccountCanvas.getActiveObject();
  currentObject.bringToFront();
}

/**
 * 上一层
 */
function itemBringForward() {
  const currentObject = handAccountCanvas.getActiveObject();
  currentObject.bringForward();
}

/**
 * 上一步
 */
function prevStepOperate() {
  return new Promise((resolve) => {
    let prev = [ ...previous ], fut = [ ...future ];
    if (prev.length <= 1) {
      // prev 只剩最后一值，已到最前
      return Toast({
        message: '已是最后一步',
        position: 'center'
      });
    }

    // prev 出栈，压入 fut
    fut.push(prev.pop());
    // 设置 prev 最后一值为当前画布内容
    handAccountCanvas.clear();
    let handAccountObject = prev[prev.length - 1];
    handAccountCanvas.loadFromJSON(handAccountObject, () => {
      handAccountCanvas.renderAll();
    });
    let handAccountJson = JSON.parse(handAccountObject);
    if (handAccountJson && handAccountJson.backgroundImage) {
      fabric.Image.fromURL(handAccountJson.backgroundImage.src, async (img) => {

        ratioNum = img.height / img.width;
        const canvasSize = await getCurrentCanvasHeight(window.innerWidth - 24, img.height); // 获取画布尺寸
        handAccountCanvas.setDimensions({
          width: canvasSize.width,
          height: canvasSize.height
        })

        handAccountCanvas.setBackgroundImage(img, handAccountCanvas.renderAll.bind(handAccountCanvas), {
          scaleX: handAccountCanvas.width / img.width,
          scaleY: handAccountCanvas.height / img.height
        });
      }, { crossOrigin: 'anonymous' });
    }

    future = [ ...fut ];
    previous = previous.splice(0, previous.length - 1);
    resolve();
  })
}

/**
 * 下一步
 */
function nextStepOperate() {
  return new Promise((resolve) => {
    let prev = [ ...previous ], fut = [ ...future ];
    if (fut.length === 0) {
      // prev 只剩最后一值，已到最前
      return Toast({
        message: '已是最后一步',
        position: 'center'
      });
    }

    // prev 出栈，压入 fut
    prev.push(fut.pop());
    // 设置 prev 最后一值为当前画布内容
    handAccountCanvas.clear();
    let handAccountObject = prev[prev.length - 1];
    handAccountCanvas.loadFromJSON(handAccountObject).renderAll();
    let handAccountJson = JSON.parse(handAccountObject);
    if (handAccountJson && handAccountJson.backgroundImage) {
      fabric.Image.fromURL(handAccountJson.backgroundImage.src, async (img) => {

        ratioNum = img.height / img.width;
        const canvasSize = await getCurrentCanvasHeight(window.innerWidth - 24, img.height); // 获取画布尺寸
        handAccountCanvas.setDimensions({
          width: canvasSize.width,
          height: canvasSize.height
        })

        handAccountCanvas.setBackgroundImage(img, handAccountCanvas.renderAll.bind(handAccountCanvas), {
          scaleX: handAccountCanvas.width / img.width,
          scaleY: handAccountCanvas.height / img.height
        });
      }, { crossOrigin: 'anonymous' });
    }
    // future = [ ...fut ];
    future = future.splice(0, future.length - 1);
    resolve();
  })
}

/**
 * 加载画布
 * params 画布参数
 * design_type  类型 1 编辑器 2 用户端
 */
function canvasLoadJson(params, design_type) {
  let backgroundImage = params.backgroundImage;
  let objectsList = params.objects;
  setCanvasBackground({
    type: 'image',
    uri: backgroundImage.src
  }).then(async (result) => {
    // handAccountCanvas.loadFromJSON(params).renderAll();
    let newWidth = result.width;
    let newHeight = result.height;
    let oldWidth = params.width;
    let oldHeight = params.height;
    let scaleXMultiplier = newWidth / oldWidth;
    let scaleYMultiplier = newHeight / oldHeight;
    backgroundImage.scaleX = backgroundImage.scaleX * scaleXMultiplier;
    backgroundImage.scaleY = backgroundImage.scaleY * scaleYMultiplier;

   for (const objects of objectsList) {

      let objectsItem = null;
      objects.scaleX = objects.scaleX * scaleXMultiplier;
      objects.scaleY = objects.scaleY * scaleXMultiplier;
      objects.left = objects.left * scaleXMultiplier;
      objects.top = objects.top * scaleXMultiplier;

      if (objects.type === 'image') {
        objectsItem = new fabric.Image.fromURL(objects.src, (img) => {
          if (objects.isMove) {
            objects.lockMovementX = true;
            objects.lockMovementY = true; 
          }
          img.set(objects);

          // 去掉控件
          img['setControlVisible']('ml', false) // 中左
          img['setControlVisible']('mb', false) // 中下
          img['setControlVisible']('mr', false) // 中右
          img['setControlVisible']('mt', false) // 中上
          img['setControlVisible']('tl', false) // 左上角
          img['setControlVisible']('tr', false) // 上右角
          img['setControlVisible']('bl', false) // 左上角

          handAccountCanvas.add(img);
        }, {crossOrigin: 'anonymous'});
      } else if (objects.type === 'textbox') {
        objectsItem = new fabric.Textbox(objects.text, objects);

        // 去掉控件
        objectsItem['setControlVisible']('ml', false) // 中左
        objectsItem['setControlVisible']('mb', false) // 中下
        objectsItem['setControlVisible']('mr', false) // 中右
        objectsItem['setControlVisible']('mt', false) // 中上
        objectsItem['setControlVisible']('tl', false) // 左上角
        objectsItem['setControlVisible']('tr', false) // 上右角
        objectsItem['setControlVisible']('bl', false) // 左上角
        objectsItem.set('editable', false); // 不可以编辑
        if (objects.isMove) {
          objectsItem.set('lockMovementX', true);
          objectsItem.set('lockMovementY', true);
        }

        // 字体加载
        if (objects.fontFamilySrc) {
          await downLoadFont({
            name: objects.fontFamily,
            url: objects.fontFamilySrc
          }).then(result => {
            
            handAccountCanvas.add(objectsItem);
          });
        } else {
          handAccountCanvas.add(objectsItem);
        }
      }
      
    }

    handAccountCanvas.renderAll();
  })
}

// 自动zoom缩放
function setZoomAuto(scale, cb) {
  const width = canvasContentEl.offsetWidth; 
  const height = canvasContentEl.offsetHeight;
  const center = handAccountCanvas.getCenter();

  const workspace = new fabric.Rect({
    fill: 'transparent',
    width,
    height,
    id: 'workspace',
  });

  handAccountCanvas.setViewportTransform([1, 0, 0, 1, 0, 0]);
  handAccountCanvas.zoomToPoint(
    new fabric.Point(center.left, center.top),
    scale,
  );
  handAccountCanvas.centerObject(workspace);
  handAccountCanvas.setWidth(width);
  handAccountCanvas.setHeight(height);
  handAccountCanvas.renderAll();
  // 超出画布不展示
  workspace.clone((cloned) => {
    handAccountCanvas.clipPath = cloned;
    handAccountCanvas.requestRenderAll();
  });
  // if (cb) cb(this.workspace.left, this.workspace.top);
}

export default {
  initCanvas,
  setCanvasBackground,
  addImage,
  discardActiveObject,
  setActiveObjectOpacity,
  addText,
  updateTextBox,
  downLoadFont,
  prevStepOperate,
  nextStepOperate,
  itemSendBackwards,
  itemBringToFront,
  itemSendToBack,
  itemBringForward,
  updatedItem,
  getObject,
  canvasLoadJson
}